package sli.sli2.channels;

import java.security.PrivateKey;
import java.security.Security;

import java.security.PublicKey;

import javax.crypto.Cipher;

import org.bouncycastle.util.encoders.Base64;

/**
 * Channel for RSA encrypted communication
 * @author Group 8, Khassraf Roman, Mueller Robin, Zischka Stefan
 *
 */
public class RSAChannel implements Channel {
	
	private TCPChannel tcpChannel = null;
	private Cipher rsaCipher = null;
	
	private PrivateKey myPrivateKey;
	private PublicKey otherPublicKey;
	
	public RSAChannel(TCPChannel tcpChannel, PrivateKey myPrivateKey, PublicKey otherPublicKey) throws Exception {
		
		this.tcpChannel = tcpChannel;
		
		this.myPrivateKey = myPrivateKey;
		this.otherPublicKey = otherPublicKey;
		
		Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
		
		//Create RSA Cipher
		rsaCipher = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding");		
	}


	@Override
	public void send(byte[] message) throws Exception {
		
		rsaCipher.init(Cipher.ENCRYPT_MODE, otherPublicKey);
		byte[] encryptedMessageByte = rsaCipher.doFinal(message);
		
		byte[] encodedMessageBase64 = encodeBase64(encryptedMessageByte);

		tcpChannel.send(encodedMessageBase64);
	}

	@Override
	public String receive() throws Exception {
		
		rsaCipher.init(Cipher.DECRYPT_MODE, myPrivateKey);
		
		String encryptedMessageBase64 = tcpChannel.receive();
		
		byte[] encryptedMessage = decodeBase64(encryptedMessageBase64);
		
		byte[] decryptedMessage = rsaCipher.doFinal(encryptedMessage);

		return new String(decryptedMessage);
	}

	/**
	 * Encodes a string into Base64 format
	 * @param message - the message to encode
	 * @return the encoded message
	 */
	private byte[] encodeBase64(byte[] message){
		
		byte[] base64Message = Base64.encode(message);
		
		return base64Message;	
	}
	
	/**
	 * Decodes a string from Base64 format
	 * @param base64Message - the message to decode
	 * @return the decoded message
	 */
	private byte[] decodeBase64(String base64Message){
		
		byte[] encryptedMessage = Base64.decode(base64Message);
		
		return encryptedMessage;
	}
}

